/*
 * AbstractNativeFile.java  0.4.0 / Nov 5, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.tools.ng;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;

import com.thoughtworks.qdox.model.JavaClass;

/**
 * Native File.
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public abstract class AbstractNativeFile {

// Private Fields. -------------------------------------------------------------

  private final JavaClass javaClass;
  private final File file;
  private final boolean doBackup;
  private NativeFileParts parts;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new NativeFile object.
   *
   * @param parent the file parent
   * @param name the file name
   * @param javaClass java class
   */
  public AbstractNativeFile(File parent, String name, JavaClass javaClass) {
    this(parent, name, javaClass, false);
  }

  /**
   * Constructs new NativeFile object.
   *
   * @param parent the file parent
   * @param name the file name
   * @param javaClass java class
   * @param doBackup if <tt>true</tt> do backup of existing file
   */
  public AbstractNativeFile(File parent, String name, JavaClass javaClass,
                            boolean doBackup) {
    file = new File(parent, name);
    this.javaClass = javaClass;
    this.doBackup = doBackup;
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Returns java class.
   *
   * @return java class
   */
  public JavaClass getJavaClass() {
    return javaClass;
  }

  /**
   * Returns native file.
   *
   * @return native file
   */
  public File getFile() {
    return file;
  }

  /**
   * Returns native file name.
   *
   * @return native file name
   */
  public String getName() {
    return file.getName();
  }

  /**
   * Loads the file.
   *
   * @throws IOException if any I/O exception occurred
   */
  public void load() throws IOException {
    if (file.exists()) {
      BufferedReader br = null;
      try {
        br = new BufferedReader(new FileReader(file));
        parts = loadParts(br);
      } finally {
        if (br != null) {
          br.close();
        }
      }
    }
  }

  /**
   * Stores the file.
   *
   * @throws IOException if any I/O exception occurred
   */
  public void store() throws IOException {
    File nativeFile = getFile();
    long nativeFileTimeStamp = nativeFile.lastModified();
    if (nativeFileTimeStamp > 0) {
      File javaClassFile = new File(javaClass.getSource().getURL().getFile());
      if (nativeFileTimeStamp > javaClassFile.lastModified()) { // NOFB
        //if (javaClassFile.getName().indexOf("Swing") == -1)
        //if (javaClassFile.getName().indexOf("Label") == -1)
        //if (javaClassFile.getName().indexOf("Component") == -1)
        return;
      }
    }
    PrintWriter pw = null;
    try {
      if (doBackup && (nativeFileTimeStamp > 0)) {
        Utils.backupFile(file);
        if (NativeGenerator.INSTANCE.isVerbose()) {
          System.out.print("Backup ");
          System.out.println(file.getAbsolutePath());
        }
      }
      if (NativeGenerator.INSTANCE.isVerbose()) {
        System.out.print("Generating ");
        System.out.println(file.getAbsolutePath());
      }
      pw = new PrintWriter(new FileOutputStream(file));
      storeParts(pw);
    } finally {
      if (pw != null) {
        pw.close();
      }
    }
  }

// Protected Methods. ----------------------------------------------------------

  /**
   * Returns file parts.
   *
   * @return file parts
   */
  protected NativeFileParts getParts() {
    return parts;
  }

  /**
   * Loads the file parts.
   *
   * @param br the buffered reader
   *
   * @return file parts

   * @throws IOException if any I/O exception occurred
   */
  protected NativeFileParts loadParts(BufferedReader br) throws IOException {
    throw new UnsupportedOperationException("File loading not supported");
  }

  /**
   * Stores the file parts.
   *
   * @param pw the print writer
   *
   * @throws IOException if any I/O exception occurred
   */
  protected void storeParts(PrintWriter pw) throws IOException {
    if (parts == null) {
      parts = createParts();
    }
    parts.store(pw);
  }

  /**
   * Creates file parts.
   *
   * @return file parts
   */
  protected abstract NativeFileParts createParts();

}
